在訪問器描述中有一組getter/setter,而不會有value跟writable。這兩個方法分別可以使用get/set寫在物件中,或者是描述器裡面。get可以不帶參數只回傳property的值,這個值可以讓set使用在設置方法,透過這個組合保護屬性或方法。
const contestant = {
contestantId: 1,
contestantName: "Alice",
get useId(){
return `${this.contestantId}`;
},
set useId(item){
this.contestantId = ++item
}
}
//直接使用
console.log(contestant.useId);//1
//另外給值執行
contestant.useId = 2
console.log(contestant.useId);//3
嘗試幾個直接寫在物件裡的函式會發現:
//有get,沒有set,在印出的時候不會報錯,但是賦值的話就會跑出錯誤訊息。
const contestant = {
contestantId: 1,
contestantName: "Alice",
get useId(){
return `${this.contestantId}`;
},
}
contestant.useId = 2//TypeError: Cannot set property useId of #<Object> which has only a getter
//set沒有get提供值的狀況下會undefined
const contestant = {
contestantId: 1,
contestantName: "Alice",
set useId(item){
this.contestantId = ++item
}
}
console.log(contestant.useId);//undefined
//get跟set取用的property不一樣,直接跳過set方法,回傳get
const contestant = {
contestantId: 1,
contestantName: "Alice",
get useId(){
return `${this.contestantName}`;
},
set useId(item){
this.contestantId = ++item
}
}
console.log(contestant.useId);//Alice
接著在屬性描述器裡面新增get/set設定:
const contestant = {
contestantId: 1,
contestantName: "Alice",
}
//把原本在物件內的函式名稱作為新的屬性名稱,並在這個方法上加上get/set
Object.defineProperty(contestant,'useId',{
get(){
return this.contestantId
},
set(item){
this.contestantId = ++item
}
})
contestant.useId = 2
console.log(contestant.useId);//3
剛剛有提到如果property中已經有get/set,那麽不會有value,但如果寫在物件裡,就不會有任何影響:
const contestant = {
contestantId: 1,
contestantName: "Alice",
}
Object.defineProperty(contestant,'useId',{
get(){
return this.contestantId
},
set(item){
this.contestantId = ++item
},
value:30
})
//TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>
const contestant = {
contestantId: 1,
contestantName: "Alice",
get useId(){
return this.contestantId
},
set useId(item){
this.contestantId = ++item
},
}
Object.defineProperty(contestant,'useId',{
value:20,
})
console.log(Object.getOwnPropertyDescriptor(contestant,'useId'));//{ value: 20, writable: false, enumerable: true, configurable: true }
最後分別來存取物件與屬性中的get/set:
把get/set函式寫在物件:
const contestant = {
contestantId: 1,
contestantName: "Alice",
get useId(){
return this.contestantId
},
set useId(item){
this.contestantId = ++item
},
}
console.log(Object.getOwnPropertyDescriptor(contestant,'useId'));
// {
// get: [Function: get useId],
// set: [Function: set useId],
// enumerable: true,
// configurable: true
// }
把get/set函式寫在屬性描述中:
const contestant = {
contestantId: 1,
contestantName: "Alice",
}
Object.defineProperty(contestant,'useId',{
get(){
return this.contestantId
},
set(item){
this.contestantId = ++item
},
})
console.log(Object.getOwnPropertyDescriptor(contestant,'useId'));
// {
// get: [Function: get],
// set: [Function: set],
// enumerable: false,
// configurable: false
// }
可以發現,在沒有更動屬性的狀況下,寫在物件的get/set方法的enumerable
與configurable
會是true
,屬性的則都是false
。